Izboljšajte vzdržljivost, berljivost in zmogljivost svoje kode Python z učinkovitimi tehnikami refaktoriranja. Naučite se praktičnih strategij in najboljših praks za izboljšanje kakovosti kode.
Tehnike refaktoriranja v Pythonu: Celovit vodnik za izboljšanje kakovosti kode
V nenehno razvijajoči se pokrajini razvoja programske opreme je ohranjanje čiste, učinkovite in razumljive kode najpomembnejše. Python, znan po svoji berljivosti, lahko še vedno podleže vonjavam kode in tehničnemu dolgu, če ni skrbno upravljan. Refaktoriranje je postopek prestrukturiranja obstoječe računalniške kode – spreminjanje faktorja – brez spreminjanja njenega zunanjega vedenja. V bistvu gre za pospravljanje vaše kode, ne da bi jo pokvarili. Ta vodnik raziskuje različne tehnike refaktoriranja v Pythonu, ponuja praktične primere in najboljše prakse za izboljšanje kakovosti vaše kode.
Zakaj refaktorirati kodo Python?
Refaktoriranje ponuja številne prednosti, vključno z:
- Izboljšana berljivost: Omogoča lažje razumevanje in vzdrževanje kode.
- Zmanjšana kompleksnost: Poenostavlja zapleteno logiko in zmanjšuje verjetnost napak.
- Izboljšana vzdržljivost: Omogoča lažje spreminjanje in razširjanje kode.
- Povečana zmogljivost: Lahko optimizira kodo za boljšo hitrost izvajanja.
- Nižji tehnični dolg: Preprečuje kopičenje kode, ki jo je težko vzdrževati ali razširiti.
- Boljša zasnova: Vodi do bolj robustne in prilagodljive arhitekture kode.
Ignoriranje refaktoriranja lahko privede do kode, ki jo je težko razumeti, spreminjati in testirati. To lahko znatno poveča čas razvoja in tveganje za vnos napak.
Kdaj refaktorirati?
Vedeti, kdaj refaktorirati, je ključnega pomena. Tukaj je nekaj pogostih scenarijev:
- Pred dodajanjem novih funkcij: Refaktoriranje obstoječe kode lahko olajša integracijo nove funkcionalnosti.
- Po popravljanju napake: Refaktoriranje okoliške kode lahko prepreči ponovitev podobnih napak.
- Med pregledi kode: Prepoznajte področja, ki jih je mogoče izboljšati, in jih refaktorirajte.
- Ko naletite na "vonjave kode": Vonjave kode so indikatorji potencialnih težav v vaši kodi.
- Redno načrtovano refaktoriranje: Vključite refaktoriranje v svoj razvojni proces kot redno dejavnost.
Prepoznavanje vonjav kode
Vonjave kode so površinski znaki, ki običajno ustrezajo globlji težavi v sistemu. Ne kažejo vedno na težavo, vendar pogosto zahtevajo nadaljnjo preiskavo.
Pogoste vonjave kode Python:
- Podvojena koda: Enaka ali zelo podobna koda, ki se pojavlja na več mestih.
- Dolga metoda/funkcija: Metode ali funkcije, ki so pretirano dolge in zapletene.
- Velik razred: Razredi, ki imajo preveč odgovornosti.
- Dolg seznam parametrov: Metode ali funkcije s preveč parametri.
- Skupine podatkov: Skupine podatkov, ki se pogosto pojavljajo skupaj.
- Primitivna obsedenost: Uporaba primitivnih podatkovnih tipov namesto ustvarjanja predmetov.
- Stavki Switch: Dolge verige stavkov if/elif/else ali stavki switch.
- Kirurški poseg s puško: Sprememba zahteva majhne spremembe različnih razredov.
- Različna sprememba: Razred se pogosto spreminja na različne načine iz različnih razlogov.
- Zavist funkcije: Metoda dostopa do podatkov drugega predmeta bolj kot do svojih lastnih podatkov.
- Verige sporočil: Stranka zahteva od enega predmeta, da zahteva od drugega predmeta, da zahteva od drugega predmeta ...
Tehnike refaktoriranja v Pythonu: Praktični vodnik
Ta razdelek podrobno opisuje več pogostih tehnik refaktoriranja v Pythonu s praktičnimi primeri.
1. Izvleček metode/funkcije
Ta tehnika vključuje jemanje bloka kode znotraj metode ali funkcije in njegovo premikanje v novo, ločeno metodo ali funkcijo. To zmanjša kompleksnost prvotne metode in omogoča ponovno uporabo izvlečene kode.
Primer:
def print_invoice(customer, details):
print("***********************")
print(f"Customer: {customer}")
print("***********************")
total_amount = 0
for order in details["orders"]:
total_amount += order["amount"]
print(f"Amount is : {total_amount}")
if total_amount > 1000:
print("You earned a discount!")
Refaktorirano:
def print_header(customer):
print("***********************")
print(f"Customer: {customer}")
print("***********************")
def calculate_total(details):
total_amount = 0
for order in details["orders"]:
total_amount += order["amount"]
return total_amount
def print_invoice(customer, details):
print_header(customer)
total_amount = calculate_total(details)
print(f"Amount is : {total_amount}")
if total_amount > 1000:
print("You earned a discount!")
2. Izvleček razreda
Ko ima razred preveč odgovornosti, nekatere od njih izvlecite v nov razred. To spodbuja načelo ene same odgovornosti.
Primer:
class Person:
def __init__(self, name, phone_number, office_area_code, office_number):
self.name = name
self.phone_number = phone_number
self.office_area_code = office_area_code
self.office_number = office_number
def get_name(self):
return self.name
def get_phone_number(self):
return f"({self.office_area_code}) {self.office_number}"
Refaktorirano:
class PhoneNumber:
def __init__(self, area_code, number):
self.area_code = area_code
self.number = number
def get_phone_number(self):
return f"({self.area_code}) {self.number}"
class Person:
def __init__(self, name, phone_number):
self.name = name
self.phone_number = phone_number
def get_name(self):
return self.name
3. Vstavljanje metode/funkcije
To je nasprotno od Izvlečka metode. Če je telo metode tako jasno kot njeno ime, lahko metodo vstavite tako, da klice metode nadomestite z vsebino metode.
Primer:
def get_rating(driver):
return more_than_five_late_deliveries(driver) ? 2 : 1
def more_than_five_late_deliveries(driver):
return driver.number_of_late_deliveries > 5
Refaktorirano:
def get_rating(driver):
return driver.number_of_late_deliveries > 5 ? 2 : 1
4. Zamenjaj začasno s poizvedbo
Namesto da bi za shranjevanje rezultata izraza uporabili začasno spremenljivko, izvlecite izraz v metodo. To se izogne podvajanju kode in spodbuja boljšo berljivost.
Primer:
def get_price(order):
base_price = order.quantity * order.item_price
discount_factor = 0.98 if base_price > 1000 else 0.95
return base_price * discount_factor
Refaktorirano:
def get_price(order):
return base_price(order) * discount_factor(order)
def base_price(order):
return order.quantity * order.item_price
def discount_factor(order):
return 0.98 if base_price(order) > 1000 else 0.95
5. Uvedba predmeta s parametri
Če imate dolg seznam parametrov, ki se pogosto pojavljajo skupaj, razmislite o ustvarjanju predmeta s parametri, da jih zajamete. To zmanjša dolžino seznama parametrov in izboljša organizacijo kode.
Primer:
def calculate_total(width, height, depth, weight, shipping_method):
# Calculation logic
pass
Refaktorirano:
class ShippingDetails:
def __init__(self, width, height, depth, weight, shipping_method):
self.width = width
self.height = height
self.depth = depth
self.weight = weight
self.shipping_method = shipping_method
def calculate_total(shipping_details):
# Calculation logic using shipping_details attributes
pass
6. Zamenjaj pogojno s polimorfizmom
Ko imate zapleten pogojni stavek, ki izbira vedenje glede na vrsto predmeta, razmislite o uporabi polimorfizma za prenos vedenja na podrazrede. To spodbuja boljšo organizacijo kode in olajša dodajanje novih vrst.
Primer:
def calculate_bonus(employee):
if employee.employee_type == "SALES":
return employee.sales * 0.1
elif employee.employee_type == "ENGINEER":
return employee.projects_completed * 100
elif employee.employee_type == "MANAGER":
return 1000
else:
return 0
Refaktorirano:
class Employee:
def calculate_bonus(self):
return 0
class SalesEmployee(Employee):
def __init__(self, sales):
self.sales = sales
def calculate_bonus(self):
return self.sales * 0.1
class EngineerEmployee(Employee):
def __init__(self, projects_completed):
self.projects_completed = projects_completed
def calculate_bonus(self):
return self.projects_completed * 100
class ManagerEmployee(Employee):
def calculate_bonus(self):
return 1000
7. Razbijanje pogojnega stavka
Podobno kot Izvleček metode, to vključuje razbijanje zapletenega pogojnega stavka v manjše, bolj obvladljive metode. To izboljša berljivost in olajša razumevanje logike pogojnega stavka.
Primer:
if (platform.upper().index("MAC") > -1) and (browser.upper().index("IE") > -1) and was_initialized() and resize > MAX_RESIZE:
# Do something
pass
Refaktorirano:
def is_mac_os():
return platform.upper().index("MAC") > -1
def is_ie_browser():
return browser.upper().index("IE") > -1
if is_mac_os() and is_ie_browser() and was_initialized() and resize > MAX_RESIZE:
# Do something
pass
8. Zamenjaj čarobno število s simbolično konstanto
Zamenjajte dobesedne numerične vrednosti z imenovanimi konstantami. To izboljša berljivost in olajša spreminjanje vrednosti pozneje. To velja tudi za druge dobesedne vrednosti, kot so nizi. Razmislite o valutnih kodah (npr. 'USD', 'EUR', 'JPY') ali kodah stanja (npr. 'ACTIVE', 'INACTIVE', 'PENDING') z globalnega vidika.
Primer:
def calculate_area(radius):
return 3.14159 * radius * radius
Refaktorirano:
PI = 3.14159
def calculate_area(radius):
return PI * radius * radius
9. Odstrani posrednika
Če razred preprosto prenaša klice v drug razred, razmislite o odstranitvi posrednika in omogočite stranki neposreden dostop do ciljnega razreda.
Primer:
class Person:
def __init__(self, department):
self.department = department
def get_manager(self):
return self.department.get_manager()
class Department:
def __init__(self, manager):
self.manager = manager
def get_manager(self):
return self.manager
Refaktorirano:
class Person:
def __init__(self, manager):
self.manager = manager
def get_manager(self):
return self.manager
10. Uvedba trditve
Uporabite trditve za dokumentiranje predpostavk o stanju programa. To lahko pomaga zgodaj odkriti napake in narediti kodo bolj robustno.
Primer:
def calculate_discount(price, discount_percentage):
if discount_percentage < 0 or discount_percentage > 100:
raise ValueError("Discount percentage must be between 0 and 100")
return price * (1 - discount_percentage / 100)
Refaktorirano:
def calculate_discount(price, discount_percentage):
assert 0 <= discount_percentage <= 100, "Discount percentage must be between 0 and 100"
return price * (1 - discount_percentage / 100)
Orodja za refaktoriranje v Pythonu
Več orodij lahko pomaga pri refaktoriranju v Pythonu:
- Rope: Knjižnica za refaktoriranje za Python.
- PyCharm: Priljubljen Python IDE z vgrajeno podporo za refaktoriranje.
- VS Code with Python Extension: Vsestranski urejevalnik z možnostmi refaktoriranja prek razširitev.
- Sourcery: Orodje za avtomatizirano refaktoriranje.
- Bowler: Orodje za refaktoriranje Facebooka za obsežne spremembe kode.
Najboljše prakse za refaktoriranje v Pythonu
- Napišite enotske teste: Pred refaktoriranjem zagotovite, da je vaša koda dobro testirana.
- Refaktorirajte v majhnih korakih: Izvedite majhne, postopne spremembe, da zmanjšate tveganje za vnos napak.
- Testirajte po vsakem koraku refaktoriranja: Preverite, ali vaše spremembe niso ničesar pokvarile.
- Uporabite nadzor različic: Pogosto shranjujte svoje spremembe, da jih po potrebi enostavno povrnete.
- Komunicirajte s svojo ekipo: Obvestite svojo ekipo o svojih načrtih refaktoriranja.
- Osredotočite se na berljivost: Dajte prednost temu, da bo vaša koda lažje razumljiva.
- Ne refaktorirajte samo zaradi refaktoriranja: Refaktorirajte, ko rešuje določen problem.
- Kjer je mogoče, avtomatizirajte refaktoriranje: Uporabite orodja za avtomatizacijo ponavljajočih se nalog refaktoriranja.
Globalni vidiki refaktoriranja
Pri delu na mednarodnih projektih ali za globalno občinstvo upoštevajte naslednje dejavnike med refaktoriranjem:
- Lokalizacija (L10n) in internacionalizacija (I18n): Zagotovite, da vaša koda pravilno podpira različne jezike, valute in oblike zapisa datuma. Refaktorirajte, da izolirate logiko, specifično za območje.
- Kodiranje znakov: Uporabite kodiranje UTF-8 za podporo širokemu naboru znakov. Refaktorirajte kodo, ki predpostavlja določeno kodiranje.
- Kulturna občutljivost: Bodite pozorni na kulturne norme in se izogibajte uporabi jezika ali podob, ki bi lahko bile žaljive. Med refaktoriranjem preglejte dobesedne nize in elemente uporabniškega vmesnika.
- Časovni pasovi: Pravilno ravnajte s pretvorbami časovnih pasov. Refaktorirajte kodo, ki predpostavlja časovni pas uporabnika. Uporabite knjižnice, kot je `pytz`.
- Ravnanje z valutami: Uporabite ustrezne podatkovne tipe in knjižnice za ravnanje z monetarnimi vrednostmi. Refaktorirajte kodo, ki izvaja ročne pretvorbe valut. Knjižnice, kot je `babel`, so uporabne.
Primer: Lokalizacija oblik zapisa datuma
import datetime
def format_date(date):
return date.strftime("%m/%d/%Y") # US date format
Refaktorirano:
import datetime
import locale
def format_date(date, locale_code):
locale.setlocale(locale.LC_TIME, locale_code)
return date.strftime("%x") # Locale-specific date format
# Example usage:
# format_date(datetime.date(2024, 1, 1), 'en_US.UTF-8') # Output: '01/01/2024'
# format_date(datetime.date(2024, 1, 1), 'de_DE.UTF-8') # Output: '01.01.2024'
Zaključek
Refaktoriranje je bistvena praksa za ohranjanje visokokakovostne kode Python. Z prepoznavanjem in obravnavo vonjav kode, uporabo ustreznih tehnik refaktoriranja in upoštevanjem najboljših praks lahko znatno izboljšate berljivost, vzdržljivost in zmogljivost svoje kode. Ne pozabite dati prednost testiranju in komunikaciji skozi celoten proces refaktoriranja. Sprejetje refaktoriranja kot neprekinjenega procesa bo privedlo do bolj robustnega in trajnostnega poteka dela razvoja programske opreme, zlasti pri razvoju za globalno in raznoliko občinstvo.